//! 集合数据操作模块
//! 实现ICollectionData接口，提供集合级别的数据操作

use std::collections::HashMap;

use async_trait::async_trait;
// use futures_util::TryStreamExt;
use mongodb::bson::{Bson, Document};
use regex::Regex;
use serde_json::Value;

use crate::{
    models::{OperateResult, TokenModel},
};
use crate::storage::storage_provider::IStorage;

/// 集合数据操作接口定义
/// 对应C#版本CollectionData接口，提供集合级别的CRUD操作
#[async_trait]
pub trait ICollectionData: Send + Sync {
    /// 列出所有集合
    async fn list_collections(&self, token: &TokenModel) -> OperateResult;

    /// 加载数据
    async fn load_data(&self, token: &TokenModel, collection_name: &str, options: Value) -> OperateResult;

    /// 聚合查询
    async fn aggregate(&self, token: &TokenModel, collection_name: &str, options: Value) -> OperateResult;

    /// 汇总统计
    async fn summary(&self, token: &TokenModel, options: Value) -> OperateResult;

    /// 插入数据
    async fn insert(&self, token: &TokenModel, collection_name: &str, data: Value) -> OperateResult;

    /// 替换数据
    async fn replace(&self, token: &TokenModel, collection_name: &str, data: Value) -> OperateResult;

    /// 设置字段
    async fn set_fields(&self, token: &TokenModel, collection_name: &str, data: Value) -> OperateResult;

    /// 更新数据
    async fn update(&self, token: &TokenModel, collection_name: &str, data: Value) -> OperateResult;

    /// 删除数据
    async fn remove(&self, token: &TokenModel, collection_name: &str, match_condition: Value) -> OperateResult;
}

/// 集合数据实现类
/// 实现ICollectionData接口，提供集合级别的数据操作
pub struct CollectionData<S: IStorage + Send + Sync + 'static + ?Sized> {
    storage: std::sync::Arc<S>,
}

impl<S: IStorage + Send + Sync + 'static + ?Sized> CollectionData<S> {
    /// 创建新的集合数据实例
    pub fn new(storage: std::sync::Arc<S>) -> Self {
        Self { storage }
    }

    /// 尝试获取集合（带验证）
    async fn try_get_collection(&self, token: &TokenModel, collection_name: &str) -> Result<Box<dyn crate::storage::storage_provider::ICollection<Document>>, String> {
        // 验证集合名称格式
        let re = Regex::new(r"^[_a-z-0-9]{5,30}$").unwrap();
        if !re.is_match(collection_name) || collection_name == "_system-objects" || collection_name.starts_with("_system-tags") {
            return Err("集合名称必须是长度为5~30个字符的小写英文字母、数字或('-','_')!".to_string());
        }

        let collection = self.storage.get_document_collection(&token.db_name(), collection_name);
        Ok(collection)
    }
}

#[async_trait]
impl<S: IStorage + Send + Sync + 'static + ?Sized> ICollectionData for CollectionData<S> {
    async fn list_collections(&self, token: &TokenModel) -> OperateResult {
        match self.storage.list_collections(&token.db_name()).await {
            Ok(collections) => {
                let mut result = HashMap::new();
                for collection_name in collections {
                    let command = Document::from_iter([("collStats".to_string(), Bson::String(collection_name.clone()))]);
                    if let Ok(stats) = self.storage.run_command(&token.db_name(), command).await {
                        result.insert(collection_name, stats);
                    }
                }
                OperateResult::success(serde_json::to_value(result).unwrap_or(Value::Null))
            }
            Err(e) => OperateResult::fail(&format!("列出集合失败: {}", e)),
        }
    }

    async fn load_data(&self, token: &TokenModel, collection_name: &str, options: Value) -> OperateResult {
        let coll_name = if collection_name.is_empty() {
            "_system-things"
        } else {
            collection_name
        };

        match self.try_get_collection(token, coll_name).await {
            Ok(collection) => {
                // 解析查询选项
                let filter = match mongodb::bson::to_document(&options) {
                    Ok(doc) => doc,
                    Err(_) => Document::new(), // 如果选项格式错误，使用空过滤器
                };

                // 实现数据加载逻辑，支持查询选项
                let results = collection.find(filter).await;
                match results {
                    Ok(results) => {
                        OperateResult::success(serde_json::to_value(results).unwrap_or(Value::Null))
                    }
                    Err(e) => OperateResult::fail(&format!("加载数据失败: {}", e)),
                }
            }
            Err(e) => OperateResult::fail(&e),
        }
    }

    async fn aggregate(&self, token: &TokenModel, collection_name: &str, options: Value) -> OperateResult {
        match self.try_get_collection(token, collection_name).await {
            Ok(collection) => {
                let pipeline = match mongodb::bson::to_document(&options) {
                    Ok(doc) => vec![doc],
                    Err(e) => return OperateResult::fail(&format!("聚合选项格式错误: {}", e)),
                };

                match collection.aggregate(pipeline).await {
                    Ok(results) => {
                        OperateResult::success(serde_json::to_value(results).unwrap_or(Value::Null))
                    }
                    Err(e) => OperateResult::fail(&format!("聚合查询失败: {}", e)),
                }
            }
            Err(e) => OperateResult::fail(&e),
        }
    }

    async fn summary(&self, token: &TokenModel, options: Value) -> OperateResult {
        // 实现汇总统计逻辑
        // 解析汇总选项，包括分组、聚合函数等
        let options_doc = match mongodb::bson::to_document(&options) {
            Ok(doc) => doc,
            Err(e) => return OperateResult::fail(&format!("汇总选项格式错误: {}", e)),
        };

        // 获取集合名称
        let collection_name = options_doc
            .get("collection")
            .and_then(|v| v.as_str())
            .unwrap_or("_system-things");

        match self.try_get_collection(token, collection_name).await {
            Ok(collection) => {
                // 构建聚合管道进行汇总统计
                let mut pipeline = Vec::new();

                // 添加匹配条件
                if let Some(match_stage) = options_doc.get("match") {
                    pipeline.push(Document::from_iter([("$match".to_string(), match_stage.clone())]));
                }

                // 添加分组条件
                if let Some(group_stage) = options_doc.get("group") {
                    pipeline.push(Document::from_iter([("$group".to_string(), group_stage.clone())]));
                }

                // 添加排序条件
                if let Some(sort_stage) = options_doc.get("sort") {
                    pipeline.push(Document::from_iter([("$sort".to_string(), sort_stage.clone())]));
                }

                // 执行聚合查询
                match collection.aggregate(pipeline).await {
                    Ok(results) => {
                        OperateResult::success(serde_json::to_value(results).unwrap_or(Value::Null))
                    }
                    Err(e) => OperateResult::fail(&format!("汇总统计失败: {}", e)),
                }
            }
            Err(e) => OperateResult::fail(&e),
        }
    }

    async fn insert(&self, token: &TokenModel, collection_name: &str, data: Value) -> OperateResult {
        match self.try_get_collection(token, collection_name).await {
            Ok(collection) => {
                let documents = match mongodb::bson::to_document(&data) {
                    Ok(doc) => vec![doc],
                    Err(e) => return OperateResult::fail(&format!("数据格式错误: {}", e)),
                };

                match collection.insert_many(documents).await {
                    Ok(_) => OperateResult::success(Value::Null), // 简化返回，因为ICollection::insert_many不返回插入ID
                    Err(e) => OperateResult::fail(&format!("插入数据失败: {}", e)),
                }
            }
            Err(e) => OperateResult::fail(&e),
        }
    }

    async fn replace(&self, token: &TokenModel, collection_name: &str, data: Value) -> OperateResult {
        match self.try_get_collection(token, collection_name).await {
            Ok(collection) => {
                let documents = match mongodb::bson::to_document(&data) {
                    Ok(doc) => vec![doc],
                    Err(e) => return OperateResult::fail(&format!("数据格式错误: {}", e)),
                };

                // 获取所有文档的ID
                let ids: Vec<Bson> = documents
                    .iter()
                    .filter_map(|doc| doc.get("id").cloned())
                    .collect();

                if !ids.is_empty() {
                    let in_doc = Document::from_iter([("$in".to_string(), Bson::Array(ids))]);
                    let filter = Document::from_iter([("id".to_string(), Bson::Document(in_doc))]);
                    match collection.delete_one(filter).await {
                        Ok(_) => {
                            match collection.insert_many(documents).await {
                                Ok(_) => OperateResult::success(Value::Null), // 简化返回，因为ICollection::insert_many不返回插入ID
                                Err(e) => OperateResult::fail(&format!("替换数据失败: {}", e)),
                            }
                        }
                        Err(e) => OperateResult::fail(&format!("删除旧数据失败: {}", e)),
                    }
                } else {
                    OperateResult::fail("没有有效的文档ID")
                }
            }
            Err(e) => OperateResult::fail(&e),
        }
    }

    async fn set_fields(&self, token: &TokenModel, collection_name: &str, data: Value) -> OperateResult {
        // 实现设置字段逻辑 - 批量更新文档的特定字段
        match self.try_get_collection(token, collection_name).await {
            Ok(collection) => {
                let data_doc = match mongodb::bson::to_document(&data) {
                    Ok(doc) => doc,
                    Err(e) => return OperateResult::fail(&format!("数据格式错误: {}", e)),
                };

                // 解析更新条件
                let filter = data_doc
                    .get("filter")
                    .and_then(|v| v.as_document())
                    .cloned()
                    .unwrap_or_else(Document::new);

                // 解析更新内容
                let update = data_doc
                    .get("update")
                    .and_then(|v| v.as_document())
                    .cloned()
                    .unwrap_or_else(Document::new);

                if update.is_empty() {
                    return OperateResult::fail("更新内容不能为空");
                }

                // 构建更新操作
                let update_doc = Document::from_iter([("$set".to_string(), Bson::Document(update))]);

                // 执行批量更新
                match collection.update_many(filter, update_doc).await {
                    Ok(_) => OperateResult::success(Value::Null), // 简化返回，因为ICollection::update_many不返回匹配和修改计数
                    Err(e) => OperateResult::fail(&format!("设置字段失败: {}", e)),
                }
            }
            Err(e) => OperateResult::fail(&e),
        }
    }

    async fn update(&self, token: &TokenModel, collection_name: &str, data: Value) -> OperateResult {
        // 实现更新数据逻辑 - 支持多种更新操作
        match self.try_get_collection(token, collection_name).await {
            Ok(collection) => {
                let data_doc = match mongodb::bson::to_document(&data) {
                    Ok(doc) => doc,
                    Err(e) => return OperateResult::fail(&format!("数据格式错误: {}", e)),
                };

                // 解析更新条件
                let filter = data_doc
                    .get("filter")
                    .and_then(|v| v.as_document())
                    .cloned()
                    .unwrap_or_else(Document::new);

                // 解析更新操作类型和内容
                let mut update_doc = Document::new();

                // 支持多种更新操作
                if let Some(set_data) = data_doc.get("$set").and_then(|v| v.as_document()) {
                    update_doc.insert("$set", set_data.clone());
                }
                if let Some(unset_data) = data_doc.get("$unset").and_then(|v| v.as_document()) {
                    update_doc.insert("$unset", unset_data.clone());
                }
                if let Some(inc_data) = data_doc.get("$inc").and_then(|v| v.as_document()) {
                    update_doc.insert("$inc", inc_data.clone());
                }
                if let Some(push_data) = data_doc.get("$push").and_then(|v| v.as_document()) {
                    update_doc.insert("$push", push_data.clone());
                }
                if let Some(pull_data) = data_doc.get("$pull").and_then(|v| v.as_document()) {
                    update_doc.insert("$pull", pull_data.clone());
                }

                if update_doc.is_empty() {
                    return OperateResult::fail("更新操作不能为空");
                }

                // 判断是更新单个文档还是多个文档
                let update_many = data_doc
                    .get("multi")
                    .and_then(|v| v.as_bool())
                    .unwrap_or(false);

                if update_many {
                    // 更新多个文档
                    match collection.update_many(filter, update_doc).await {
                        Ok(_) => OperateResult::success(Value::Null), // 简化返回，因为ICollection::update_many不返回匹配和修改计数
                        Err(e) => OperateResult::fail(&format!("更新多个文档失败: {}", e)),
                    }
                } else {
                    // 更新单个文档
                    match collection.update_one(filter, update_doc).await {
                        Ok(_) => OperateResult::success(Value::Null), // 简化返回，因为ICollection::update_one不返回匹配和修改计数
                        Err(e) => OperateResult::fail(&format!("更新单个文档失败: {}", e)),
                    }
                }
            }
            Err(e) => OperateResult::fail(&e),
        }
    }

    async fn remove(&self, token: &TokenModel, collection_name: &str, match_condition: Value) -> OperateResult {
        match self.try_get_collection(token, collection_name).await {
            Ok(collection) => {
                let filter = match mongodb::bson::to_document(&match_condition) {
                    Ok(doc) => doc,
                    Err(e) => return OperateResult::fail(&format!("匹配条件格式错误: {}", e)),
                };

                match collection.delete_one(filter).await {
                    Ok(_) => OperateResult::success(Value::Null), // 简化返回，因为ICollection::delete_one不返回删除计数
                    Err(e) => OperateResult::fail(&format!("删除文档失败: {}", e)),
                }
            }
            Err(e) => OperateResult::fail(&e),
        }
    }
}